<?php

namespace Kcdns\Service\Oauth;

use Think\Log;
class Oauth
{

    static $instace;

    private $O = false;

    private $type = false;

    public static function getInstance()
    {
        return self::$instace ?: (self::$instace = new self());
    }


    //发起Oauth授权
    public function getAuthinfo($type)
    {
        if (empty($type)) {
            throw new \Exception('参数错误');
        }
        $this->type = $type;

        $this->getOauth();

//        Log::w_log('start-weixin--code:'.I('get.code'));
        if ($code = I('get.code')) {
            $oauth[$type] = $this->callBack($code, $type);
//            Log::w_log(json_encode($oauth));
            session("_OAUTH_INFO_", $oauth);
            return $oauth[$type];
        }
        $this->gateway();
    }

    //授权网关 跳转
    private function gateway()
    {
        $requri = substr($_SERVER["REQUEST_URI"], 1);
        $pos = (strpos($requri, '?') === false) ? '?' : '&';
        $host = U("/", NULL, true, true);
        $callback = $host . $requri;

        $url = $this->O->getRequestCodeURL($callback);

        $msg = '<!DOCTYPE html><html> <head>	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />	<meta http-equiv="Content-Language" content="utf-8" />	<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport">	<title>loading</title> </head> <body>  <blockquote style="font-size:14px">正在载入...</blockquote> </body></html>';
        redirect($url, 1, $msg); // 跳转到授权页面
        exit();
    }

    //获取授权信息
    public function getOauthByKey($openid, $type)
    {
        $where = array(
            'type' => $type,
            'openid' => $openid
        );
        $record = M('Oauth')->where($where)->find() ?: array();
        if ($record) {
            //数据解密
            $record['token'] = kcone_think_decrypt($record['token']);
            $record['refresh_token'] = kcone_think_decrypt($record['refresh_token']);
            $record['user_info'] = kcone_think_decrypt($record['user_info']);
        }
        return $record;
    }

    //授权回调
    private function callBack($code = '', $type)
    {
        // 腾讯微博需传递的额外参数
        $extend = null;
        // 请妥善保管这里获取到的Token信息，方便以后API调用
        // 调用方法，实例化SDK对象的时候直接作为构造函数的第二个参数传入
        $token = $this->O->getAccessToken($code, $extend);
        Log::w_log(json_encode($token));
        // 获取当前登录用户信息
        if (is_array($token)) {
//Log::write(11);
            $openid = $this->O->openid();

            //获取用户信息
            if($type == 'weixin_full'){
                $user_auth_data = $this->O->getUserInfoFull();
            }else{
                $user_auth_data = $this->O->getUserInfo();
            }

            Log::w_log("获取userInfo：".json_encode($user_auth_data));

            $this->checkAuthInfo($user_auth_data);

            return $this->saveOauth($this->type, $openid, $token, $user_auth_data);
        } else {
            throw new \Exception('授权失败');
        }
    }

    //获取oauth驱动SDK
    private function getOauth()
    {
        $this->O = OauthSDK::getInstance($this->type, null, $this->loadConfig($this->type));
        $this->typeId = $this->O->getTypeId();
        return true;
    }

    private function checkAuthInfo($data = array())
    {
        if (!$data) {
            return;
        }

        $need = array(
            'nickname'
        );

        // 昵称非法字符过滤
        $data['nickname'] = preg_replace('|[^a-zA-Z0-9\x{4e00}-\x{9fa5}]|u', '*', $data['nickname']);
        foreach ($need as $key) {
            if (!isset($data[$key]) || $data[$key] == '') {
                throw new \Exception('授权参数异常：' . $key);
            }
        }
    }

    //加载oauth配置信息
    private function loadConfig($type)
    {

        $where = array(
            'type' => strtolower($type),
            'status' => 1
        );
        $payConfig = M('OauthSettings')->where($where)->find();
        if (!$payConfig) {
            throw new \Exception('无效的OAUTH方式');
        }
        $payConfig['config'] = json_decode(kcone_think_decrypt($payConfig['config']), true);
        $config = array();
        foreach ($payConfig['config'] as $item) {
            $config[$item['key']] = $item['val'];
        }

        $config['mode'] = $payConfig['mode'];

        return $config;

//
//        $cfg= array(
//            'weixin'=>array(
//                'APP_KEY'=>'4f47a0ea2a0fc9dae801dae247fa3942',
//                'APP_SECRET'=>'58e4d44e550d0f7ee0a23d6b02d9b0db',
//                'GetRequestCodeURL' => 'http://center.x.kcdns.net/oauth_wechat/connect/oauth2/authorize',
//                'GetAccessTokenURL' => 'http://center.x.kcdns.net/oauth_wechat/sns/oauth2/access_token',
//                'ApiBase' => 'http://center.x.kcdns.net/oauth_wechat/',
//            ),
//        );

    }

    //存储授权信息
    private function saveOauth($type, $openid, $tokenData, $userInfo)
    {
        if (!$oauthInfo = $this->getOauthByKey($openid, $type)) {
            //insert
            $data = array(
                'type' => $type,
                'openid' => $openid,
                'token' => kcone_think_encrypt($tokenData['access_token']),
                'refresh_token' => kcone_think_encrypt($tokenData['refresh_token']),
                'expires' => $tokenData['expires_in'],
                'data' => kcone_think_encrypt(json_encode($userInfo)),
                'create_time' => date('Y-m-d h:i:s'),
                'update_time' => date('Y-m-d h:i:s'),
                'nums' => 0,
            );
            M('Oauth')->add($data);
        } else {
            //update
            $data = array(
                'type' => $type,
                'openid' => $openid,
                'token' => kcone_think_encrypt($tokenData['access_token']),
                'refresh_token' => kcone_think_encrypt($tokenData['refresh_token']),
                'expires' => $tokenData['expires_in'],
                'user_info' => kcone_think_encrypt(json_encode($userInfo)),
                'update_time' => date('Y-m-d h:i:s'),
                'nums' => array('exp', '`nums`+1'),
                'data' => kcone_think_encrypt(json_encode($userInfo)),
            );
            M('Oauth')->where(array('type' => $type, 'openid' => $openid))->save($data);
        }
        return array(
            'type' => $type,
            'openid' => $openid,
            'token' => $tokenData['access_token'],
            'user_info' => $userInfo
        );
    }

}
